package com.scap.dfs.controller;

import java.io.IOException;
import java.io.PrintWriter;
import java.lang.reflect.Field;
import java.math.BigDecimal;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;

import javax.servlet.http.HttpServletResponse;

import org.apache.log4j.Logger;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.Transaction;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.ui.ModelMap;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;

import com.scap.dfs.dao.DailyCalFormulaConfigDao;
import com.scap.dfs.dao.DailyCalFormulaDao;
import com.scap.dfs.dao.TrnDailyDao;
import com.scap.dfs.model.DailyCalFormula;
import com.scap.dfs.model.DailyCalFormulaConfig;
import com.scap.dfs.model.TrnDaily;
import com.scap.dfs.service.TrnDailyProcessService;
import com.scap.dfs.service.impl.TrnDailyProcessServiceImpl;

@RequestMapping(value = "/trn")
@Controller
public class TrnDailyController {
	
	@Autowired
	TrnDailyProcessService trnDailyProcessService;
	
	final static Logger logger = Logger.getLogger(TrnDailyController.class);
	
	@Autowired
	TrnDailyDao trnDailyDao;
	
	@Autowired
	DailyCalFormulaDao calFormulaDao;
	
	@Autowired
	DailyCalFormulaConfigDao configCalDao;
	
	
	
	@RequestMapping(value = "")
	public String welcomePage(ModelMap map){
		map.addAttribute("name","Cape");
		return "trnDaily/index";
	}
	
	
	
	
	String hospitalCode = "011";
//	String hospitalCode = "00009";
	
	@RequestMapping(value = "/calculate", method = RequestMethod.POST)
	@ResponseBody 
	public String progressbarMotivation(HttpServletResponse response,@RequestParam("beginDate")String beginDate
			,@RequestParam("endDate")String endDate){
		
//		System.out.println("beginDate : "+beginDate);
//		System.out.println("endDate : "+endDate);
		
		System.out.println("Process Start");
		//Begin process
		String processStatus = processBasicAllocate(hospitalCode,beginDate,endDate,"0000");
		//End process
		
		
		String issueTrnString = "";
		for(TrnDaily trnDaily:issueTrnDailyList){
			String issueReason = "";
			
			
				
				if(trnDaily.getDoctorCategoryCode()==""||trnDaily.getDoctorCategoryCode()==" "
						||trnDaily.getDoctorCategoryCode().equals("")||trnDaily.getDoctorCategoryCode().equals(" ")
						||trnDaily.getDoctorCategoryCode()==null||trnDaily.getDoctorCategoryCode().equals(null)){
					issueReason = "Doctor category code not found in 'DOCTOR' table.";
					
				}
				else{
					issueReason = "DRCAT:'"+trnDaily.getDoctorCategoryCode()+"'  is not specific in configuration.";
				}
				
				trnDaily.setPatientName(issueReason);
			
			
			
			issueTrnString = issueTrnString 
					+ ",{\"doctorCode\":\""+trnDaily.getDoctorCode()+"\""
					+ ",\"lineNo\":\""+trnDaily.getId().getLineNo()+"\""
					+ ",\"invNo\":\""+trnDaily.getId().getInvoiceNo()+"\""
					+ ",\"reason\":\""+trnDaily.getPatientName()+"\"}";
		}
		
		if(issueTrnString.length()>0){
		issueTrnString = issueTrnString.substring(1,issueTrnString.length());
		}
		
		
		String json = "{\"trnSize\":\""+trnSize+"\""
				+ ",\"trnProcessStatus\":\""+processStatus+"\""
				+ ",\"trnSizeDone\":\""+doneTrnDailyList.size()+"\""
				+ ",\"trnSizeIssue\":\""+issueTrnDailyList.size()+"\""
				+ ",\"trnIssue\": ["+issueTrnString+"]}";
		
		
		System.out.println("Process done");
		
		return json;
		
		
	}
	
	
	List<TrnDaily> issueTrnDailyList;
	List<TrnDaily> doneTrnDailyList;
	int trnSize = 0;
	
	@RequestMapping(value = "/calculate_processing", method = RequestMethod.POST)
	@ResponseBody 
	public String processing(){
		int doneSize = doneTrnDailyList.size();	
		double doneSizeTemp = doneSize;
		double trnSizeTemp = trnSize;
		int result = (int) ((doneSizeTemp/trnSizeTemp)*100);
		
		return result+"% "+"("+(int)doneSizeTemp+" of "+(int)trnSizeTemp+")";
	}
	
	@RequestMapping(value = "/rollback", method = RequestMethod.POST)
	@ResponseBody 
	public String rollback(HttpServletResponse response,@RequestParam("beginDate")String beginDate
			,@RequestParam("endDate")String endDate){
		
//		System.out.println("beginDate : "+beginDate);
//		System.out.println("endDate : "+endDate);
		
		//Begin roll-back
		String rollbackStatus = trnDailyProcessService.rollbackBasicAllocate(hospitalCode, beginDate, endDate, "0000");
		//End roll-back
		if(rollbackStatus=="success"||rollbackStatus.equals("success")){
			return "Roll-back success.";
		}
		else{
			return rollbackStatus;
		}
	}
	
	public String processBasicAllocate(String hospitalCode, String beginDate,
			String endDate,String userId) {
		
		issueTrnDailyList = new ArrayList<TrnDaily>();
		doneTrnDailyList = new ArrayList<TrnDaily>();
		trnSize = trnDailyDao.countGetList(hospitalCode, beginDate, endDate);
		
		
		List<TrnDaily> trnDailyList = trnDailyDao.getList(hospitalCode, beginDate, endDate);
		List<DailyCalFormula> dailyCalFormulaList = calFormulaDao.getListByHospitalCodeOrderByFlowNumber(hospitalCode);

		
		
		//Each formula
		for(DailyCalFormula dailyCalFormula : dailyCalFormulaList){
			System.out.println("------------------------Begin formula------------------------");
		
			System.out.println("COLUMN NAME1 : "+dailyCalFormula.getVar1ColumnName());
			System.out.println("COLUMN NAME2 : "+dailyCalFormula.getVar2ColumnName());
			System.out.println("COLUMN NAME3 : "+dailyCalFormula.getVar3ColumnName());
			
			int formulaId = dailyCalFormula.getId().getFormulaId();
			List<DailyCalFormulaConfig> configs = configCalDao.getLisByHospitalCodeAndFormulaId(hospitalCode,formulaId);
			
			String column1Name = dailyCalFormula.getVar1ColumnName();
			String column2Name = dailyCalFormula.getVar2ColumnName();
			String column3Name = dailyCalFormula.getVar3ColumnName();
			String attr1Name = trnDailyDao.getAttributeNameByColumnName(column1Name);
			String attr2Name = trnDailyDao.getAttributeNameByColumnName(column2Name);
			String attr3Name = trnDailyDao.getAttributeNameByColumnName(column3Name);
			System.out.println("attr1Name : "+attr1Name);	
			System.out.println("attr2Name : "+attr2Name);	
			System.out.println("attr3Name : "+attr3Name);	
			
			//Each config
			System.out.println("------------Begin configs------------");	
			for(DailyCalFormulaConfig config:configs){
				String column1Value = config.getId().getVar1Value();				
				String column2Value = config.getId().getVar2Value();				
				String column3Value = config.getId().getVar3Value();
				
				try{
					
					for(TrnDaily trnDaily:trnDailyList){
					
						
						//Begin for trnDailyList
						if(trnDaily.getComputeDailyDate()==null||trnDaily.getComputeDailyDate()==""){

							Object o = trnDaily;
							Class<?> c = o.getClass();
							
							boolean isPassed = true;
							
							if(attr1Name!=null&&isPassed){
								Field f1 = c.getDeclaredField(attr1Name);
								f1.setAccessible(true);
								String value1 = (String) f1.get(o);
								if(value1==column1Value||value1.equals(column1Value)){
									isPassed = isPassed&&true;
								}
								else{
									isPassed = isPassed&&false;
								}
							}
							if(attr2Name!=null&&isPassed){
								Field f2 = c.getDeclaredField(attr2Name);
								f2.setAccessible(true);
								String value2 = (String) f2.get(o);
								if(value2==column2Value||value2.equals(column2Value)){
									isPassed = isPassed&&true;
								}
								else{
									isPassed = isPassed&&false;
								}
							}
							if(attr3Name!=null&&isPassed){
								Field f3 = c.getDeclaredField(attr3Name);
								f3.setAccessible(true);
								String value3 = (String) f3.get(o);
								if(value3==column3Value||value3.equals(column3Value)){
									isPassed = isPassed&&true;
								}
								else{
									isPassed = isPassed&&false;
								}
							}
							
							String admissionType = trnDaily.getAdmissionTypeCode();
							String invoiceType = trnDaily.getId().getInvoiceType();
							
							if(config.getId().getAdmissionType().contains(admissionType)&&isPassed){
								isPassed = isPassed&&true;
							}
							else{
								isPassed = isPassed&&false;
							}
							
							if(config.getId().getInvoiceType().contains(invoiceType)&&isPassed){
								isPassed = isPassed&&true;
							}
							else{
								isPassed = isPassed&&false;
							}
							
							if(isPassed){
								System.out.println("IsPassed : "+isPassed);
								double sharingBegin = config.getId().getSharingBegin().doubleValue();
								double sharingEnd = config.getId().getSharingEnd().doubleValue();
								double amountAftDiscount = trnDaily.getAmountAftDiscount().doubleValue();
								Double sharingBaht = config.getSharingBaht()!=null?config.getSharingBaht().doubleValue():null;
								Double sharingPercent = config.getSharingPercent()!=null?config.getSharingPercent().doubleValue():null;
								String textRevenue = config.getTaxRevenue();
								
								
								if(sharingBegin<=amountAftDiscount&&(amountAftDiscount<=sharingEnd||sharingEnd==0)){
										
										//Set sharing money
										BigDecimal drAmt;
										if(sharingPercent>0.00){
											//This is sharing percent
											drAmt = new BigDecimal(amountAftDiscount*(sharingPercent/100));
											trnDaily.setDrAmt(drAmt);
											
											//Set NorAllocatePCT
											trnDaily.setNorAllocatePct(new BigDecimal(sharingPercent));
											trnDaily.setNorAllocateAmt(new BigDecimal(0.00));
										}
										else{
											//This is sharing baht
											if(sharingBaht>amountAftDiscount){
												drAmt = new BigDecimal(amountAftDiscount);
											}
											else{
												drAmt = new BigDecimal(sharingBaht);
											}
											trnDaily.setDrAmt(drAmt);
											
											//SetNorAllocateAmt
//											trnDaily.setNorAllocateAmt(new BigDecimal(sharingBaht));
											trnDaily.setNorAllocateAmt(trnDaily.getDrAmt());
											trnDaily.setNorAllocatePct(new BigDecimal(0.00));
										}
										
										//SetHpAmt
										BigDecimal hpAmt = new BigDecimal(amountAftDiscount - trnDaily.getDrAmt().doubleValue());
										hpAmt = hpAmt.setScale(2, BigDecimal.ROUND_HALF_EVEN);
										trnDaily.setHpAmt(hpAmt);
										
										
										
										//Set tax type
										trnDaily.setTaxTypeCode(config.getTaxType());
										
										//Set DoctorTaxAmt
										BigDecimal taxRate = config.getTaxRate();
										BigDecimal taxAmtResult = null;
										if(textRevenue=="Before"||textRevenue.equals("Before")){
											//Before
											taxAmtResult = new BigDecimal(taxRate.doubleValue()*amountAftDiscount);
											
											//Set TaxFromAllocate ('Y'-->After , 'N'-->Before )
											trnDaily.setTaxFromAllocate("N");
											
										}else if(textRevenue=="After"||textRevenue.equals("After")){
											//After
											taxAmtResult = new BigDecimal(taxRate.doubleValue()*trnDaily.getDrAmt().doubleValue());
											
											//Set TaxFromAllocate ('Y'-->After , 'N'-->Before )
											trnDaily.setTaxFromAllocate("Y");
											
										}
										taxAmtResult= taxAmtResult.setScale(2, BigDecimal.ROUND_HALF_EVEN);
										trnDaily.setDoctorTaxAmt(taxAmtResult);
										
										//Set formulaId
										trnDaily.setBasicAllocateFormulaId(config.getId().getFormulaId().toString());
										
										//Set UserId
										trnDaily.setUserId(userId);
										
										
										
										//Set IsGuarantee ('Y','N')
										if(config.getIsGuarantee()=="Y"||config.getIsGuarantee().equals("Y")){
											trnDaily.setIsGuarantee("Y");
										}
										else{
											trnDaily.setIsGuarantee("N");
										}
										
										//Set IsGuaranteeFromAllocate ('Y','')
										if(config.getIsGuaranteeFromAlloc()=="Y"||config.getIsGuaranteeFromAlloc().equals("Y")){
											trnDaily.setIsGuaranteeFromAlloc("Y");
										}
										else{
											trnDaily.setIsGuaranteeFromAlloc("");
										}
										
										
										
										
										String result = trnDailyProcessService.updateTrnDailyForBasicAllocateProcess(trnDaily);//With userId
										
										if(result=="success"||result.equals("success")){
											doneTrnDailyList.add(trnDaily);
										}
										else{
											//Reason tell why cannot save
											trnDaily.setPatientName(result);
										}
										
								}
							}
						}
						
						//End for trnDailyList
					}
					
					
					for(TrnDaily trnDone:doneTrnDailyList){
						trnDailyList.remove(trnDone);
					}
					
				}
				catch(IllegalAccessException e){
					logger.error(e);
				} catch (NoSuchFieldException e) {
					logger.error(e);
				} catch (SecurityException e) {
					logger.error(e);
				} 
			}
			System.out.println("------------Done configs------------");
			System.out.println("------------------------End formula------------------------");
		}
		
		
		//Update all trnDailyList
		issueTrnDailyList = trnDailyList;
		
		
		System.out.println("trnDailyList size : "+trnDailyList.size());
		System.out.println("doneTrnDailyList size : "+doneTrnDailyList.size());
		System.out.println("issueTrnDailyList size : "+issueTrnDailyList.size());
		
		
		if(issueTrnDailyList.size()==0){
			return "Done";
		}
		else{
			return "Found problem";
		}
	}
	





}
